﻿using System.Collections;
using UnityEngine;
using ScFramework.Core;
using System.Collections.Generic;
using System;

public partial class PhysicsProcessSubmodule : SubmoduleBase
{

    public override void OnInit(object args)
    {
        base.OnInit(args);
#if DEBUG
        PhysicsProcessDebuger._instance = this;
#endif
        if (args != null)
        {
            var data=JsonUtil.Deserialize<SceneData>( Resources.Load<TextAsset>((args as string).Split('.')[0]).text);
            Debug.Assert(data.sysDatas.ContainsKey(BelongingSystem.Default) == false);
            foreach(var x in data.sysDatas)
            {
                _main.Get<ProcedureManager>().Current.GetSubmodule<SubPhysicsManager>().SetAllData(x.Key, x.Value);
            }
   
        }
        Get<IEntityDataManager>().InitData(GetMapDataFromFile());
        //临时设置状态为在游戏中
       /* if (_main.Get<UserManager>().IsHost)
        {
            _main.Get<UserManager>().SetUserState(_main.Get<UserManager>().UserID, UserState.OnGame);
        }*/
        _main.Get<UserManager>().RegisterUserEvent(WhenFromCombineToGame, UserState.OnCombine, UserState.OnGame, 1);
        Get<ICollisionManager>().SetSubPhysicsMgr(_main.Get<ProcedureManager>().Current.GetSubmodule<SubPhysicsManager>());
    }
    void WhenFromCombineToGame(int id)
    {
        var list =

            Get<ISharedEntityDataManager>().GetAllData().FindAll(
                s => s.GetComponentData<SComBody>()!=null).ConvertAll(s=>new SComBodyVEx(s.GetComponentData<SComBody>()));
        list.RemoveAll(s => s.UserID!=id||s.PresentPos != 1);
        foreach(var x in list)
        {
            x.PresentPos = 0;
        }
    //    if (GameMode.Instance.CheckIfCanToGame(list))
   //     {
            Dispatch(ObjectPresentPosEvent.ToWorld, new ObjectPresentPosChangeArgs
            {
                LastPresentPos=ObjectPresentPos.Bench,
                Entities=list

            });
     //   }
        
    }
    public override void FixedUpdate()
    {
        Get<IPhysicsClient>().SolveMessage();

        foreach(var x in Gets<IRestrictUpdater>())
        {
            x.UpdateBeforeFunc();
        }
        Physics2D.SyncTransforms();


        Get<IFuncManager>().OnKeysAndDoKeyAction(Get<IKeyEventManager>().SendKeyEvents());

        base.FixedUpdate();
        foreach (var x in Gets<IRestrictUpdater>())
        {
            x.UpdateBeforePhysicSimu();
        }

        Dispatch(PhysicsProcessEvent.PhysicsSimulate,Time.fixedDeltaTime);
        Get<ICollisionManager>().SolveCollision();
    }
    public override void LateFixedUpdate()
    {
        base.LateFixedUpdate();
        Get<IPhysicsClient>().Send();
     //   SendMessage();
    }
    [RegisterEvent(PhysicsProcessEvent.StartCombine)]
    void StartCombine(Tuple<List<Entity>,Vector3>args)
    {
        Debug.Assert(GetSystemModule<UserManager>().GetUserState(GetSystemModule<UserManager>().UserID) == UserState.OnGame);
        GetSystemModule<UserManager>().SetUserState(GetSystemModule<UserManager>().UserID, UserState.OnCombine);
        GetSystemModule<MessageManager>().Get<CombineUIAction>().DispatchMessage(CombineUIAction.StartCombine, this, new ObjectArgs<Vector3>(args.Item2));
    }


    Byte[] GetMapDataFromFile()
    {
        return null;
    }


}


public enum PhysicsProcessEvent
{
    StartCombine,

    /// <summary>
    /// 筛选实例
    /// </summary>
    EntityData_SelectInstance,

    /// <summary>
    /// 同步实例
    /// </summary>

    SyncInstance,
    /// <summary>
    /// 一组实例被同步创建
    /// </summary>
    InstancesCreated,
    InstancesToDelete,

    /// <summary>
    /// 物理模拟
    /// </summary>
    PhysicsSimulate,

    Physics_RequireComp,

    Physics_ReceiveComp,
}

/// <summary>
/// 当物体已经到达某位置时产生的事件
/// </summary>
public enum ObjectPresentPosEvent
{
    ToWorld,
    ToBag,
    ToBench
}


public class ObjectPresentPosChangeArgs
{
    public ObjectPresentPos LastPresentPos = ObjectPresentPos.Null;
    public List<SComBodyVEx> Entities;
}


#if DEBUG
[DebugCmdType("物理数据")]
public static class PhysicsProcessDebuger 
{
    public static IPhysicsDebug _instance;

    [DebugCmd("列出实体预设")]
    public static string ListItemPrefab()
    {
        string ans = "Follow Prefabs Are Listed:\n";
        for(int i = 0; i < EntityUtilities.entityPrefabs.Count; i++)
        {
            ans += $"name={EntityUtilities.entityPrefabs[i].name} id={i}\n";
        }
        return ans;
    }
    [DebugCmd("列出实体")]
   public static string ListEntity()
    {
        if (_instance == null)
        {
            return "Instance not settled";
        }
        return _instance.ListEntity();
    }
    [DebugCmd("列出组件","实体ID")]
    public static string ListComp(ushort eid)
    {
        if (_instance == null)
        {
            return "Instance not settled";
        }
        return _instance.ListComponent(eid);
     }
    [DebugCmd("列出value", "实体ID","组件ID")]
    public static string ListValues(ushort eid,ushort vid)
    {
        if (_instance == null)
        {
            return "Instance not settled";
        }
        return _instance.ListValues(eid, vid);
    }
    [DebugCmd("创建实体","预设名称")]
   public static string CreateEntity(string name)
    {
        if (_instance == null)
        {
            return "Instance not Settled";
        }
        return _instance.CreateEntity(name);
    }
    [DebugCmd("删除实体", "实体ID")]
    public static string DeleteEntity(ushort eid)
    {
        if (_instance == null)
        {
            return "Instance not Settled";
        }
        return _instance.DeleteEntity(eid);
    }
}
public partial class PhysicsProcessSubmodule : IPhysicsDebug
{
    public override void OnDestroy()
    {
        base.OnDestroy();
        PhysicsProcessDebuger._instance = null;
    }
    public string ChangeEntityIntValue(ushort eid, string comp, string value, int v)
    {
        return ChangeEntityValue(eid, comp, value, v);

    }

    public string ChangeEntityValue(ushort eid, string comp, string value, object v)
    {
        var compT = Type.GetType(comp);
        if (compT == null) return "No such Component with type name = " + comp;

        var e = Get<IEntityDataManager>().GetEntityData(eid);
        if (e == null) return "No such entity with eid = " + eid;

        var cp = e.GetComponentData(compT);
        if (cp == null) return $"Entity {eid} has no comp {comp}";

        uint vid;
        try
        {

            vid = EntityUtilities.GetValueID(cp, value);
        }
        catch (KeyNotFoundException)
        {
            return $"comp {comp} has no value named {value}";
        }

        if (EntityUtilities.GetValueType(cp.CompIdentity, vid.right()) != v.GetType())
        {
            return $"type not match,need type {EntityUtilities.GetValueType(cp.CompIdentity, vid.right())}";
        }

        Dispatch(EntityDataEvent.ValueChange, new ValueChangeArgs
        (
            eid, vid, v
        )); ;
        return $"Value change message dispatched successful(maybe fail to change value if value type not right)";

    }

    public string CreateEntity(string name)
    {
        Dispatch(EntityDataEvent.Create, EntityUtilities.GetIdByName(name));
        return "Create message dispatched Successful";
    }
    public string DeleteEntity(ushort eid)
    {
        if (Get<IEntityDataManager>().GetEntityData(eid) == null)
        {
            return $"Entity with eid = {eid } not found";
        }
        Dispatch(EntityDataEvent.Delete, eid);
        return "Entity delete message dispatched successful";
    }
    public string ListEntity()
    {
        string ans = "____________________________\n";
        if (Get<IEntityDataManager>() != null)
        {
            foreach(var x in Get<IEntityDataManager>().GetEntitiesCollection())
            {
                ans += $"EntityID={x.EntityIdentity.right()} EntityPrefabID={x.EntityIdentity.left()} ";
                ans += $"EntityName={EntityUtilities.GetEntityName(x.EntityIdentity.left())} ";
                ans += $"Component Count={x.ComponentDatas.Count}\n";
            }
            ans += "____________________________\n";
            return ans;

        }
        else
        {
            return "Fail to access EntityDataManager";
        }
    }
    public string ListComponent(ushort eid)
    {
        if (Get<IEntityDataManager>().GetEntityData(eid) == null)
        {
            return "Fail to get entity with eid = " + eid;
        }
        string ans = "Entity ID = " + eid + "\n";
        foreach (var x in Get<IEntityDataManager>().GetEntityData(eid).ComponentDatas)
        {
            ans += $"component id = {x.CompIdentity.right()} component type = {x.ComponentType} value count = { EntityUtilities.GetValueCnt(x.ComponentType)}\n";
        }

        return ans;
    }
    public string ListValues(ushort eid, ushort cid)
    {
        if (Get<IEntityDataManager>().GetEntityData(eid) == null)
        {
            return "Fail to get entity with eid = " + eid;
        }
        if (Get<IEntityDataManager>().GetEntityData(eid).GetComponentData(cid) == null)
        {
            return $"fail to get compoent with eid = {eid} cid = {cid}";
        }
        Type ctype = Get<IEntityDataManager>().GetEntityData(eid).GetComponentData(cid).ComponentType;
        string ans = $"eid = {eid} cid = {cid}\n";
        var cnt = EntityUtilities.GetValueCnt(ctype);
        for (ushort i = 0; i < cnt; i++)
        {
            ans += $"vid = {i} vname={EntityUtilities.GetValueName(ctype, (ushort)i)} value= {Get<IEntityDataManager>().GetEntityData(eid).GetComponentData(cid).GetValue(EntityUtilities.GetValueType(Get<IEntityDataManager>().GetEntityData(eid).EntityIdentity.left().combine(cid), i), i)}\n";

        }
        return ans;
    }

    public string StoreCurrentData(string path)
    {
        if (Get<IEntityDataManager>() != null)
        {
            throw new NotImplementedException();
        }
        else
        {
            return "Fail to access EntityDataManager";
        }
    }

    public string LoadData(string path)
    {
        throw new NotImplementedException();
    }
}
public interface IPhysicsDebug
{
    string CreateEntity(string name);
    string ChangeEntityIntValue(ushort eid, string comp, string value,int v);
    string DeleteEntity(ushort eid);

    string ListEntity();
    string ListComponent(ushort eid);
    string ListValues(ushort eid, ushort cid);

    string StoreCurrentData(string path);
    string LoadData(string path);

}
#endif